package dungeonDigger.entities;

import java.util.HashMap;
import java.util.Map;

import org.newdawn.slick.Input;
import org.newdawn.slick.SpriteSheet;

import dungeonDigger.entities.templates.TypeTemplate;
import dungeonDigger.enums.CreatureStat;
import dungeonDigger.enums.DamageType;

public abstract class Agent extends GameObject {
	protected String						name;
	private SpriteSheet						spriteSheet;
	private TypeTemplate					typeTemplate	= null;
	private HashMap<CreatureStat, Integer>	stats			= new HashMap<>();
	private HashMap<CreatureStat, Integer>	baseStats		= new HashMap<>();
	private float							currentHitPoints;
	private float							maxHitPoints;
	transient Input							inputs			= null;
	transient protected Ability				queuedAbility;

	public Agent() {
		// Setup basic stats
		this.baseStats.put( CreatureStat.STRENGTH, 10 );
		this.baseStats.put( CreatureStat.DEXTERITY, 10 );
		this.baseStats.put( CreatureStat.INTELLIGENCE, 10 );
		this.baseStats.put( CreatureStat.WISDOM, 10 );
		this.baseStats.put( CreatureStat.CONSTITUTION, 10 );
		this.baseStats.put( CreatureStat.CHARISMA, 10 );
		this.baseStats.put( CreatureStat.MOVEMENT, 6 );
		this.setStats( this.baseStats );
	}

	public float takeDamage(float amount) {
		return this.takeDamage( new DamageTypeMatrix( new DamageType[] { DamageType.NORMAL }, new float[] { 100 } ), amount );
	}

	public float takeDamage(DamageTypeMatrix matrix, float amount) {
		return this.takeDamage( matrix, amount, 0 );
	}

	/** Applies damage to this object spread across the Damage Type provided within the matrix and over the duration provided [NOT
	 * IMPLEMENTED].
	 * @param matrix
	 * @param amount
	 * @param durationInMS
	 * @return The amount of final cumulative damage done after resistances, armor, etc. */
	public float takeDamage(DamageTypeMatrix matrix, float amount, int durationInMS) {
		float damageDone = 0;
		for( Map.Entry<DamageType, Float> entry : matrix.getMatrix().entrySet() ) {
			if( entry.getValue() > 0 ) {
				float thisDmg = entry.getValue() * amount;
				// TODO: apply resistances, weaknesses, armor, etc
				this.setCurrentHitPoints( this.getCurrentHitPoints() - thisDmg );
				damageDone += thisDmg;
			}
		}
		return damageDone;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setQueuedAbility(Ability ability) {
		this.queuedAbility = ability;
	}

	public Ability getQueuedAbility() {
		return this.queuedAbility;
	}

	public float getCurrentHitPoints() {
		return currentHitPoints;
	}

	public void setCurrentHitPoints(float currentHitPoints) {
		this.currentHitPoints = currentHitPoints;
		if( this.currentHitPoints <= 0 && this instanceof Mob ) {
			( (Mob)this ).die();
		}
	}

	public float getMaxHitPoints() {
		return maxHitPoints;
	}

	public void setMaxHitPoints(float maxHitPoints) {
		this.maxHitPoints = maxHitPoints;
	}

	public SpriteSheet getSpriteSheet() {
		return spriteSheet;
	}

	public void setSpriteSheet(SpriteSheet spriteSheet) {
		this.spriteSheet = spriteSheet;
	}

	public TypeTemplate getTypeTemplate() {
		return typeTemplate;
	}

	public void setTypeTemplate(TypeTemplate typeTemplate, boolean... applying) {
		if( applying == null ) {
			applying = new boolean[] { false };
		}
		if( this.getTypeTemplate() == null && !applying[0] ) {
			typeTemplate.applyTo( this );
		} else if( this.getTypeTemplate() == null && applying[0] ) {
			this.typeTemplate = typeTemplate;
		}
	}

	public HashMap<CreatureStat, Integer> getStats() {
		return stats;
	}

	public void setStats(HashMap<CreatureStat, Integer> stats) {
		this.stats = stats;
	}

	public HashMap<CreatureStat, Integer> getBaseStats() {
		return baseStats;
	}
}
